perm filename HAL.CLN[HAL,HE] blob
sn#149515 filedate 1975-03-04 generic text, type T, neo UTF8
COMMENT ⊗ VALID 00025 PAGES
RECORD PAGE DESCRIPTION
00001 00001
00007 00002 INTRODUCTION TO HAL: A SIMPLE TRANSLATION FROM WAVE.
00008 00003 SYNTAX OF HAL
00014 00004 MORE SYNTAX. DECLARATIONS
00016 00005 STILL MORE SYNTAX: WORLDS, MACROS.
00017 00006 SEMANTICS OF HAL.
00027 00007 SIMPLE MOVES
00043 00008 SOME SAMPLES OF HAL CODE, WHICH DEMONSTRATE THE SYNTAX
00046 00009 COMPLEX MOVES.
00055 00010 TYPES OF VARIABLES.
00064 00011 ARITHMETIC.
00075 00012 DEFERRED EVALUATION
00079 00013 DATA STRUCTURES FOR REPRESENTATION OF OBJECTS.
00081 00014 COMPILE TIME AND RUNTIME MODIFICATION OF VARIABLES
00087 00015 CONTROL STRUCTURES.
00091 00016 IDEAS WHICH MUST BE THOUGHT OUT. THEIR TIME HAS ALMOST COME.
00095 00017 THE FOLLOWING PAGES ARE FOR COMMENTS & COMPLAINTS BY POTENTIAL USERS.
00096 00018 ... SAMPLE PROGRAM : SLIP_OVER (OCT 10)
00102 00019 ... SAMPLE PROGRAM : PUT_PISTON_IN_VISE (OCT 12)
00108 00020 ... A REWORK OF PUT_PISTON_IN_VISE (W/ SETS, RESTORES ...NOV 6)
00118 00021 ... RANDOM COMMENTS
00120 00022 ... SAMPLE PROGRAM : BOLT_ON_FROB (OCT 22)
00128 00023 ... MORE COMMENTS (WHILE I'M THINKING OF THEM)
00129 00024 ...
00130 00025 ...
00131 ENDMK
⊗;
INTRODUCTION TO HAL: A SIMPLE TRANSLATION FROM WAVE.
SAMPLE OF WAVE:
VECT DF
0 0 -40
VECT MV
0 0 80
FORCE DF NIL
STOP NIL MV
FREE 1 Z
SCREW 60
MERGE
CHANGE NIL 0 NIL 0 30
EQUIVALENT HAL CODE:
MOVE YELLOW
TO ⊗ COMMENT: ⊗ means current location;
ON TORQUE(ZVECT(YELLOW)) > 80 DO STOP
COMMENT: STOP CAUSES THE ARM TO STOP, THEREBY TERMINATING THE MOVE;
USING TIME ≥ 30
MAINTAINING FORCE(ZVECT(YELLOW)*-40), FREE(ZVECT(YELLOW))
DURING SCREW(60);
COMMENT: COMMANDS OF SCREWING HAVE TIME LIMITS, WHICH
IN THIS CASE IS SET BY THE COMPILER.
SYNTAX OF HAL
NOTE ON THE BNF: * IS KLEENE STAR, [] IS OPTIONAL, {} ARE BRACKETS.
THIS PAGE IS BEING UPDATED WHENEVER NEW IDEAS OCCUR.
LAST UPDATE: 5/01/74
<PROGRAM> ::= <STATEMENT>
<STATEMENT> ::= <BLOCK> | <ASSIGNMENT> | <COMMAND> | <LABEL>: <STATEMENT> |
<STOP> | <DONE>| <DECLARATION>
IF <BOOL EXPR> THEN <STATEMENT> ELSE <STATEMENT> |
<FOR STATEMENT> | <ASSUME> | <CHECK> | <DYNAMIC ATTACHMENT STATEMENT> |
<WHENEVER STATEMENT> | <SIMULTANEOUS BLOCK> | <WORLD MANIPULATION>
<BLOCK> ::= BEGIN [<STRING>] [<STATEMENT> { ; <STATEMENT>}*] END
<SIMULTANEOUS BLOCK> ::=
COBEGIN <STATEMENT> [; <STATEMENT>]* COEND
<COMMAND> ::= <SIMPLE MOVE> | <COMPLEX MOVE> | <CENTER> | <DRIVE>
| <SEARCH> | <VISE COMMAND> | <FINGERS COMMAND>
<SIMPLE MOVE> ::=
{MOVE | GO} <CONTROLLABLE FRAME>
TO <FRAME EXPR> [THEN <STATEMENT>]
[TRACING <PARAMETERIZED FRAME>]
[MAINTAINING ORIENTATION]
[FROM <FRAME EXPR>]
[VIA <DECORATED FRAME LIST>]
[USING <PERFORMANCE SPEC LIST>]
[DURING <STATEMENT>]
[ON <BOOL EXPR> DO <STATEMENT> [, <BOOL EXPR> DO <STATEMENT>]* ]
[MEANWHILE <STATISTICS REQUEST LIST>]
<SIMULTANEOUS MOVE> ::=
{MOVE | GO} <CONTROLLABLE FRAME PAIR>
TO <FRAME PAIR EXPR> [THEN <STATEMENT>]
[TRACING <PARAMETERIZED FRAME PAIR>]
[MAINTAINING ORIENTATION]
[FROM <FRAME PAIR EXPR>]
[VIA <DECORATED FRAME LIST>]
[USING <PERFORMANCE SPEC LIST>]
[DURING <STATEMENT>]
[ON <BOOL EXPR> DO <STATEMENT> [, <BOOL EXPR> DO <STATEMENT>]* ]
[MEANWHILE <STATISTICS REQUEST LIST>]
<CONTROLLABLE FRAME> ::= <ARM> | <FRAME ATTACHED TO A CONTROLLABLE FRAME>
<CONTROLLABLE FRAME PAIR> ::=
'{ <CONTROLLABLE FRAME> , <CONTROLLABLE FRAME> '}
<ARM> ::= {YELLOW | BLUE}
<DECORATED FRAME LIST> ::= <DECORATED FRAME> [, <DECORATED FRAME LIST>]
<DECORATED FRAME> ::= <FRAME EXPR> [:<DECOR>]* [THEN <STATEMENT>]
<DECOR> ::= VEL=<VECTOR EXPR> | DURATION {≥ | ≤} <ARITH EXPR> |
| APPROACH = <VECT EXPR> | DEPARTURE = <VECTOR EXPR>
<PERFORMANCE SPEC LIST> ::= <PERF SPEC> [, <PERF SPEC LIST>]
<PERF SPEC> ::= DURATION {≥ | ≤} <ARITH EXPR> | FORCE = <VECT EXPR>
| FREE = <VECT EXPR LIST> | DEPARTURE = <VECT EXPR>
| APPROACH = <VECT EXPR> | MASS=<SCALAR>
<PARAMETERIZED FRAME> ::=
{{LOC = <PARAMETERIZED VECTOR>, ORIENT = <PARAMETERIZED ORIENTATION>} |
<PARAM FRAME EXPR> } FOR <PARAM> ← <SCALAR> BY <GRAIN> UNTIL <SCALAR>
[WITHIN <TOLERANCE>]
<GRAIN> ::= <SCALAR>
<SEARCH> ::=
SEARCH <CONTROLLABLE FRAME>
{ACROSS <PLANE EXPR> | NORMAL_TO <VECTOR EXPR>}
INCREMENT = <SCALAR EXPR>
REPEATING <STATEMENT>
[THEN <STATEMENT>]
[FROM etc]
[DURING etc]
[ON etc]
<CENTER> ::=
CENTER <ARM>
{ACROSS <PLANE EXPR> | NORMAL_TO <VECTOR EXPR>}
[DURING etc]
[ON etc]
<DRIVE> ::=
DRIVE <ARM> (<INTEGER EXPR>)
TO <SCALAR EXPR>
[TRACING <PARAMETERIZED SCALAR>]
[DURING etc]
[ON etc]
[THEN etc]
<WHENEVER STATEMENT> ::= WHENEVER <BOOL EXPR> DO <STATEMENT>
<CONSTRAINT STATEMENT> ::=
CONSTRAIN [<CONSTRAINT> ,]* <CONSTRAINT>
<CONSTRAINT> ::=
{LIKE: 0 ≤ THETA < π ; OR 3*X < Y + Z}
<LINEAR PARAMETER EXPR> (<|>|≤|≥|=) <SEXP>
<LINEAR PARAMETER EXPR> ::=
<PARAMETER> | <SEXP> * PARAMETER | <LIN PAR EXP> + <LIN PAR EXP>
MORE SYNTAX. DECLARATIONS
<DECLARATION> ::=
<TYPE> <IDENTIFIER LIST> |
<TYPE> ARRAY <IDENTIFIER LIST> <BOUNDS LIST>
<TYPE> ::=
SCALAR
PARAMETER
PLANE
VECTOR
FRAME
TRANS
ATOM
PROPERTY
STRING
LABEL
<UNITS STATEMENT> ::= <UNITS OPTION LIST>
<UNITS OPTION> ::= CM | INCHES | JIFFIES | SECONDS | MILLISECONDS |
KG | GM | LBS | OZ | RADIANS | DEGREES | BOLLES | EULER
| TAYLOR | GEOMED
<PROCEDURE DECLARATION> ::=
PROCEDURE <NAME> (<ARGUMENT LIST>);
BEGIN
ASSUME <ARG> AT <FRAME EXPR> [WITHIN <TOLERANCE>];
one assumption is required for each frame in the arg list.
<STATEMENT>
END
<TOLERANCE> ::= <VECTOR>
STILL MORE SYNTAX: WORLDS, MACROS.
<WORLD MANIPULATION> ::=
SAVE WORLD <WORLD NAME> | RESTORE WORLD <WORLD NAME>
<ASSUMPTION> ::= ASSUME <FRAME> AT <FRAME EXPR>
<CHECK> ::= CHECK <WORLD BOOLEAN>
<ATTACH STATEMENT> ::=
ATTACH <FRAME> TO <FRAME>
<DETACH STATEMENT> ::=
DETACH <FRAME>
SEMANTICS OF HAL.
HAL obeys traditional ALGOL block structure. There are
variables of several types, which must be declared. The entire
program is a statement. In order to allow flexible editing of a
running program, it is a good idea to name important blocks with
strings, as in SAIL. Then it should be possible to modify source
code when in the interactive mode of HAL.
The purpose of blocks is to 1) separate variables, allowing
for reclamation of storage, 2) keeping the scope of simultaneity
under control (as it is not legal to leave a block until all
processes in it have terminated).
SIMPLE MOVES
A move is simple if it involves only one arm. There are two
varieties of move: MOVE and GO. The former causes a smooth
trajectory to be compiled. The latter lets the servo do all the
calculation, and the arm will stop after each segment of the motion.
Certain things must be specified in any move. First is the
arm which must be moved. This can be specified directly (as YELLOW
or BLUE) or by specifying a frame which is to be moved. A FRAME is
a location with an orientation. Wherever the hand is constitutes a
frame. YELLOW is a frame. Certain objects will have frames on them
also. It is possible to attach frames to arms. So if the hand is
holding a frob, it is perfectly reasonable to request that the frob
be moved to a particular location. So if FROB is a frame attached
to BLUE, then both FROB and BLUE are <controllable frame>s.
Next, the destination must be specified. This is specified
as a frame, of course. MOVE BLUE TO F1 means that at the end of the
motion, the frame BLUE should coincide with the frame F1. MOVE FROB
TO F2 means that at the end of the motion, FROB coincides with F2.
There is a convenience about destinations: They can be specified in
terms of where the arm (or controllable frame) is at the start of
the motion. The symbol for this is ⊗. That is, ⊗ is a frame which
is the location and orientation of the controllable frame at the
start of the motion.
Let us assume for the sake of clarity that an arm is the
controllable frame. Bear in mind that this is not necessary; it
just makes the discussion less wordy.
There are several options which may be used in conjunction
with the MOVE to force certain things to happen. The THEN
<statement> construction tells what to do if the move is completed
without error of any kind. Due to the block nature of HAL, this
statement can in fact be itself very complex.
TRACING is another option. It allows the user greater
control over the exact trajectory chosen for the move. One can
trace a path at whatever speed one wants. The path, or
<parameterized frame>, is a specification of what frame the arm is
to go through for each value of the parameter. Of course, one also
specifies what the relation between the parameter and real time is.
It is also possible to state the grain of the motion and the
tolerance that is acceptable (as a real distance in 3-space).
Next comes the option of MAINTAINING ORIENTATION. This
causes the trajectory computed by HAL to try to maintain the same
hand orientation throughout the motion. It is required that the
final orientation supplied by the user be the same as the initial
orientation for this to work at all.
The FROM construct is used to tell the compiler where the
arm is at the moment. This should be used if otherwise the compiler
would have no way of knowing from which point it should begin the
trajectory calculation.
The VIA list list is a set of intermediate frames which the
arm is to pass through. This may not be used with a TRACING motion.
At each of the intermediate frames, several conditions may be
specified. These include velocity, upper or lower bounds on the
time required to reach this frame from the previous one on the list,
and how the frame is to be approached and departed. Also, using a
THEN construct, one can specify some action which is to be taken at
the time this frame is achieved, such as setting a flag or
initiating an action for the other arm. It is not legal to initiate
action on the arm currently in motion.
USING lists a set of modes under which the motion is to be
performed. These can include duration control, force applied in
some direction, which directions should be free from position
feedback, and what the departure and approach should be (if it
desired to override the defaults, which are properties of the frames
involved at the beginning and end of motion).
The DURING field specifies that another statement is to be
executed simultaneously with this motion. It can either have the
statement in situ, or it can specify the label of the desired
statement (which had better exist somewhere in the program).
ON requests that certain conditions be continually monitored
during motion. These can be any sort of condition, including flag
checking, force checking, and time checking. If any monitored
condition triggers, the DO part associated with it will be
executed. This can include the statement STOP. The implementation
of this will very likely be by means of SAIL events.
MEANWHILE specifies some sort of statistics request. The
form of this has yet to be worked out.
Perhaps something like OCCUPYING <VOLUME> should be added, so
that some primitive compilation-time collision avoidance can be
implemented.
SIMPLE MOVES
A move is simple if it involves only one arm. There are two
varieties of move: MOVE and GO. The former causes a smooth
trajectory to be compiled. The latter lets the servo do all the
calculation, and the arm will stop after each segment of the motion.
Certain things must be specified in any move. First is the
arm which must be moved. This can be specified directly (as YELLOW
or BLUE) or by specifying a frame which is to be moved. A FRAME is
a location with an orientation. Wherever the hand is constitutes a
frame. YELLOW is a frame. Certain objects will have frames on them
also. It is possible to attach frames to arms. So if the hand is
holding a frob, it is perfectly reasonable to request that the frob
be moved to a particular location. So if FROB is a frame attached
to BLUE, then both FROB and BLUE are <controllable frame>s.
Next, the destination must be specified. This is specified
as a frame, of course. MOVE BLUE TO F1 means that at the end of the
motion, the frame BLUE should coincide with the frame F1. MOVE FROB
TO F2 means that at the end of the motion, FROB coincides with F2.
There is a convenience about destinations: They can be specified in
terms of where the arm (or controllable frame) is at the start of
the motion. The symbol for this is ⊗. That is, ⊗ is a frame which
is the location and orientation of the controllable frame at the
start of the motion.
Let us assume for the sake of clarity that an arm is the
controllable frame. Bear in mind that this is not necessary; it
just makes the discussion less wordy.
There are several options which may be used in conjunction
with the MOVE to force certain things to happen. The THEN
<statement> construction tells what to do if the move is completed
without error of any kind. Due to the block nature of HAL, this
statement can in fact be itself very complex.
TRACING is another option. It allows the user greater
control over the exact trajectory chosen for the move. One can
trace a path at whatever speed one wants. The path, or
<parameterized frame>, is a specification of what frame the arm is
to go through for each value of the parameter. Of course, one also
specifies what the relation between the parameter and real time is.
It is also possible to state the grain of the motion and the
tolerance that is acceptable (as a real distance in 3-space).
Next comes the option of MAINTAINING ORIENTATION. This
causes the trajectory computed by HAL to try to maintain the same
hand orientation throughout the motion. It is required that the
final orientation supplied by the user be the same as the initial
orientation for this to work at all.
The FROM construct is used to tell the compiler where the
arm is at the moment. This should be used if otherwise the compiler
would have no way of knowing from which point it should begin the
trajectory calculation.
The VIA list list is a set of intermediate frames which the
arm is to pass through. This may not be used with a TRACING motion.
At each of the intermediate frames, several conditions may be
specified. These include velocity, upper or lower bounds on the
time required to reach this frame from the previous one on the list,
and how the frame is to be approached and departed. Also, using a
THEN construct, one can specify some action which is to be taken at
the time this frame is achieved, such as setting a flag or
initiating an action for the other arm. It is not legal to initiate
action on the arm currently in motion.
USING lists a set of modes under which the motion is to be
performed. These can include duration control, force applied in
some direction, which directions should be free from position
feedback, and what the departure and approach should be (if it
desired to override the defaults, which are properties of the frames
involved at the beginning and end of motion).
The DURING field specifies that another statement is to be
executed simultaneously with this motion. It can either have the
statement in situ, or it can specify the label of the desired
statement (which had better exist somewhere in the program).
ON requests that certain conditions be continually monitored
during motion. These can be any sort of condition, including flag
checking, force checking, and time checking. If any monitored
condition triggers, the DO part associated with it will be
executed. This can include the statement STOP. The implementation
of this will very likely be by means of SAIL events.
MEANWHILE specifies some sort of statistics request. The
form of this has yet to be worked out.
Perhaps something like OCCUPYING <VOLUME> should be added, so
that some primitive compilation-time collision avoidance can be
implemented.
SEMANTICS CONTINUED.
SEARCHES
A SEARCH is very much like a move. It is a means of
specifying repeated action in a spiral. As with a MOVE, it is
necessary to name a controllable frame which is to be moved. The
THEN, FROM, and ON constructs are exactly as they are for MOVEs.
One must stipulate what the plane of the search is to be.
This is accomplished in either of two ways: ACROSS <plane> means the
search is to take place in the plane specified. If the controllable
frame (say the hand) is in fact not in that plane at the start, then
the plane parallel to the given one, through the hand, will be used.
It is assumed that the hand is already at the center of the search.
The other alternative is to say NORMAL_TO <vector>. This will
specify the plane you want for the search. Actually, the servo does
almost all the calculating for this; it is fed the normal and the
increment size.
Most important for the search is the REPEATING construct.
It is by this that one specifies what motion is to be performed at
each iteration of the search. It is advisable that the motion cause
the arm to return to the point at which it began, in order to assume
the same plane at the onset of each iteration. If this is not done,
then the servo will move it back each time anyway. When the search
succeeds (and it is the duty of the user to specify what success
means for each search) the search can be terminated in either of two
ways: by setting a flag in the REPEATING and checking it in the ON,
or by using the construct DONE inside the DURING at the right place.
Note that the DONE must have the label of the SEARCH, not that of
the MOVE.
RUN-TIME MODIFICATION OF TRAJECTORIES
All trajectories are modified before execution to bring them
into line with current values of frames. After every move, the
run-time location of the hand is determined, and all frames fixed to
it are updated; if there is any discrepancy between the run-time and
compile-time understanding of where the frame is, the servo will go
the the right place nonetheless. The ASSUME statement tells the
compiler where it should expect the frame to be.
CENTER
It happens at times that the hand is positioned around an
object, and it is desired to center the hand around it, and close
the fingers at the same time. This is accomplished by means of the
CENTER command. As with the SEARCH command, it takes as an argument
the plane in which the centering is to take place, either by the
construct ACROSS <plane> or by NORMAL_TO <vector>. The
specifications of DURING, THEN, and ON are just as in a search.
More complex centering actions can be added when more sophisticated
touch sensing is added. Some such actions can be done as it stands;
the ON construct is used to add an offset to the trajectory upon
touch or force sensing. The ADD construct has not yet been fully
worked out.
DRIVE
If it is desired to drive only one joint at a time, or to
explicity control several joints at once, the way to do this is with
a DRIVE. The particular joint is specified, as is the destination.
In this context, ⊗ means the current location of this joint, in
radians (or inches). As for a simple move, it is possible to
specify the exact nature of the motion by means of a TRACING
construct. To get several joints going in unison, use the DURING
construct. The other options are just as in MOVE. It is expected
that this will only be used for arm maintenance and testing.
WORLDS
A world is a collection of defined objects, frames, vectors,
etcetera, along with their values and structure of attachment. When
a world is saved, all this information is written out on the disk
somewhere. When it is restored, the compiler picks up its version of
the world, and generates code for the servo to reload its version.
The purpose of this is to provide safe places in the HAL code at
which one can stop for the night, or to which one can return upon
failure of some experimental code. Note that no provision is made
for the real world to be restored; this is up to the user.
SOME SAMPLES OF HAL CODE, WHICH DEMONSTRATE THE SYNTAX
IF L THEN BEGIN OUTSTR("SOMETHING WRONG"); SCREW(-20) UNTIL TORQUE(Z)>10 END
ELSE
M1: MOVE YELLOW
TO C THEN BEGIN Q ← TRUE; T←T+1; ATTACH A TO YELLOW; STOP BLUE END
VIA B:VEL=A1, D:DURATION≥20 THEN Q←FALSE
USING DURATION≥20, FORCE=M*3, FREE=(T,V), APPROACH=(0,0,U)
DURING SCREW(60)
ON VEL(1)>40 DO ER←2, TORQUE(Z)>50 DO STOP, P= TRUE DO
BEGIN P←FALSE; GOTO M2 END comment: 3 conditions checked;
to do a box search:
M10: SEARCH YELLOW
PLANE P comment: will take plane parallel to P through current hand;
INCREMENT .1
REPEATING
BEGIN "PROBE"
GO YELLOW
TO ⊗ + .1*Z
ON FORCE(Z)>20 DO DONE
END
To turn a crank of radius R, assuming it lies in the X-Y plane and
that the hand is holding the crank at (R,0) in that plane:
MOVE YELLOW
TRACING
LOC = (R*COS(β), R*SIN(β),0) + ⊗ - (R, 0, 0),
ORIENT = ORIENT(⊗),
FOR β ← 0 BY .1 UNTIL 2*PI
MAINTAINING FREE(@ - (⊗ - (R, 0, 0)))
To lift a wrench held by both arms, straight up 10 inches:
MOVE {YELLOW, BLUE}
TRACING
LOC.YELLOW = ⊗.YELLOW + β*Z,
LOC.BLUE = @.YELLOW + ⊗.BLUE - ⊗.YELLOW,
ORIENT.BLUE = ORIENT(⊗.BLUE),
ORIENT.YELLOW = ORIENT(⊗.YELLOW),
FOR β ← 0 BY .1 UNTIL 10
MAINTAINING FREE.BLUE(@.YELLOW - @.BLUE)
COMPLEX MOVES.
The following are some random thoughts concerning what sort of
coordination is needed between two cooperating arms.
Time coordination: Independent trajectories, but some control over
when each achieves its objectives. This can be done entirely by
simple moves using the DURING or COBEGIN constructs and suitable
state variables.
Space coordination: This inherently requires some sort of time
coordination as well. It is perhaps best to consider the arms in
question as one device, with say 12 joints, and a trajectory should
be created accordingly.
Here is a rough idea on how to truly coordinate two arms in a
non-TRACE type trajectory. Say we want a regular trajectory to
location B for the yellow, and we want the blue to maintain the same
relation to yellow as it now has. Note that if the purpose of this
is to heft a heavy frob, the orientations of the two hands had
better remain the same, and the current orientation must be the same
as at frame B.
This brings up an important point. For coordinated motions
(as well as for some simple moves) it is desirable to specify the
orientations throughout the motion. TRACE allows (nay, demands)
this. MOVE should also allow it.
MOVE {YELLOW, BLUE}
TO {B, *}
COORDINATING LOC.BLUE = LOC.YELLOW + ⊗.BLUE - ⊗.YELLOW
MAINTAINING FREE.BLUE(@.YELLOW - @.BLUE)
MAINTAINING ORIENT = {ORIENT(⊗), ORIENT(⊗)};
Some space coordination can be achieved by specifying moves
in both arms and demanding that certain intermediate points be
achieved in time unison. This could be done either by explicitly
specifying the time for each segment or by using a combined VIA
list, of the form
VIA {AYEL,ABLU},{BYEL,BBLU}, etc.
The construct of COBEGIN is meant for independent
simultaneous motion. Each of the statements in the block is begun
more or less simultanously; the block is not terminated until the
slowest statement has finished. There are a few restrictions to such
a block: None of the statements may be labeled (for it is illegal to
jump into the block); there must be no GOTOs in the block, the
devices used by the statements must be disjoint (there must not be
simultanous use of the blue arm by two statements); some sort of
space-used checking will very likely be implemented, and a warning
printed upon compilation if a collision is possible.
Collision avoidance:
Use of two arms severely worsens the complexity of this
problem, which even in the simpler case of one arm has not been
systematically (or even seriously) attacked.
One method that has been suggested is to consider all of
space-time divided up into regions of suitable size. These regions
are to be regarded as resources which allow only one user. Several
difficulties with this approach: 1) There would be an enormous
amount of overhead in checking which resources a given move uses. 2)
Having discovered that a calculated trajectory enters forbidden
territory, it is not at all clear what to do to correct the
trajectory to avoid it. Some modification of the current
table-avoiding system might be usable. In any case, it would not be
discovered that there is any difficulty until after the trajectory
has been calculated. This is itself an expensive calculation. 3)
Some trajectory calculations will perforce be left until run time.
In the run-time environment, it will be very difficult to do checks
on resources. Note: there is serious objection to any trajectory
calculation during run time.
The following is derived from the ideas in the JPL paper at the AI
conference.
Let there be a new datatype, type FREEWAY. It is a sequence of
frames along which the arm is to be allowed to travel. The sequence
is computed to avoid explicitly stated and default obstacles (which
can include other stated freeways). Here is an example:
FREEWAY F1, F2, F3;
FRAME A, B, C, D, E, F;
code to set up the frames;
PAVE F1 FOR BLUE FROM A TO C VIA B;
PAVE F3 FOR BLUE FROM A TO B AVOIDING F WITH RADIUS=5;
PAVE F2 FOR YELLOW FROM D TO E AVOIDING F1, F3;
MOVE BLUE TO C
ALONG F1
DURING BEGIN MOVE YELLOW TO E ALONG F2 END;
Whenever a freeway is paved (as opposed to declared), it is
checked against those obstacles which it must avoid. The paving of a
freeway will also compute trajectories along its length. When a
motion is performed along a freeway, the motion will enter the
freeway as soon as possible and will stay on it as long as it can.
Perhaps the servo will control automatically the entrances and exits
as errors to preplanned trajectories.
If it is not possible to pave a new freeway due to the
proximity of another paved freeway, an attempt can be made to
reroute the conflicting freeway, maintaining, of course, the
constraints under it was first paved.
Freeway paving is very expensive, for it involves extensive
calculations. It is recommended that all paving be done with respect
to stable variables. Paving through fuzzy points is most likely
pretty safe too.
There are esthetic objections to freeways. Therefore, until
overwhelming indication to the contrary arises, we will perform
collision avoidance solely by means of VIA lists, thereby putting
the responsibility for collision avoidance squarely on the shoulder
of the user.
TYPES OF VARIABLES.
SCALAR Used for times, angles, etc. The units being used are
dependent on the UNITS statement, which tells the compiler that when
a time, say, is required, the scalar is to be interpreted in jiffies;
when a distance is needed, the scalar is in meters. The defaults
have not been decided; suggestions are welcome. Note that inside the
compiler, and inside the runtime, all measurements will be in some
uniform system, most likely centimeters, milliseconds, grams.
A PARAMETER is a variable which can be bound to a scalar, but
is usually used only in a partially constrained sense. An example is
"x where x ≥ 3". The constraints on parameters may be in terms of
other parameters, such as "where x+y=4". The purpose of parameters
is to be able to specify scalars (and hence vectors, frames, and
transforms) in an incomplete way. Thus a legal vector constant is
"(3 x y) WHERE x-y>5".
A VECTOR is an ordered triple of reals specifying a directed
distance wrt a given frame. Default is table frame. Vectors may be
fixed to a frame. This is the usual case for vectors defined wrt any
frame other than the table. It is possible to have a "free" vector,
that is it takes on meaning only when used in a calculation, and then
assumes the frame of the object to which it is arithmefied. The
vector constant is (s s s) where s is a scalar expression (which
includes expressions using parameters). This can be taken to mean a
translation (in x, y, z of the frame by which this vector is defined)
or a rotation (in whatever mode of angles currently being used).
Standard forms for rotations are Euler angles (rotations about z,
x', z''), Bolles angles (rotations about x, y, z), and Taylor angles
(z, x', y'). Geomed angles are different: (a, b, c) where this
specifies the vector of rotation, and the magnitude is the angle of
rotation. Since the internal representation is (hopefully)
independent of which idea is meant, there should be no trouble.
A FRAME is a location with an orientation. It has two basic
interpretations, which are really the same. It can be used to
specify a hand position, and it can be used to define the location
and orientation of any object. The default frame of reference is the
table coordinates. New frames are defined wrt old frames. They are
described by a pair of vectors: one for position and one for
orientation. The constant is v≡v where v1 is the location and v2 is
the orientation. Frames also have an optional deproach (which is six
numbers, for location and orientation wrt the frame itself) and an
optional mass. FRAMEs can be declared FIXed to another frame (not
necessarily the one via which they were specified). Whenever the
value of a FRAME changes, all the frames and vectors which are fixed
to it are automatically updated, both at compile time and at run
time. Thus a frob held in the hand can have its frame fixed to the
hand frame. If the hand moves, so does the frob frame.
A TRANS is a device for moving a vector or frame elsewhere.
A PLANE is a vector, which specifies the normal direction
and the distance of the plane from the origin.
An ATOM is an entity consisting of a set of properties. The
properties can themselves be atoms, lists of atoms, or arithmetic
constants. The type of any property must be declared before the
property is used, or some default will be selected. There is a set
of standard properties assosiated with each object atom; see the
later page discussing this. As in LISP, there are mechanisms to
accomplish these manipulations: (1) Add a new property or change
current value: propname(atom) ← value. (2) Delete a property:
propname(atom) ← NULL. (3) Reference a property. propname(atom) is
the expression which has the desired value. In all these, propname
must have been declared, eg: SCALAR LIST PROPERTY X,Y; VECTOR
PROPERTY LENGTH; ATOM LIST PROPERTY DESCENDENTS.
ARITHMETIC.
`s' = scalar or parameter, `v' = vector , `f' = frame,
`p' = plane, `t' = trans.
frame expressions:
v ≡ v v1 is a location, v2 is an orentation
f + v v is a translation
f ∂ v v is a rotation
f +← v v is a location which is munged into f.
f ∂← v v is an orientation which is munged into f.
t * f
s * f moves away from table origin
∀ f deferred frame
trans expressions:
f → f how to get from f1 to f2
v | v v1 is a translation, v2 is a rotation
t + v v is a translation
t ∂ v v is a rotation
t * t
t +← v v is a translation
t ∂← v v is a rotation
∀ t deferred trans
vector expressions:
v + v v2 is a translation
v ∂ v v2 is a rotation
t * v
v . v dot product
f - f difference wrt location ( a translation )
f / f difference wrt orientation ( a rotation )
s * v dilation
∀ v deferred vector
plane expressons:
p + v v is a translation
p ∂ v v is a rotation
t * p
s * p moves away from the origin
∀ p deferred plane
scalar expressions:
s + s
s * s
s - s
s / s
|v| magnitude of v
∀ s deferred scalar
Predefined constants and variables:
⊗ is the location of the arm at start of motion.
@ is the location of the arm at time of evalutation, which is
assumed to be continuous during motion.
XVECT(FRAME) is a unit X vector in FRAME. Default FRAME is TABLE.
YVECT(FRAME) is a unit Y vector in FRAME. Default FRAME is TABLE.
ZVECT(FRAME) is a unit Z vector in FRAME. Default FRAME is TABLE.
XSCAL(FRAME,VECTOR) is the X-coordinate of the vector as seen from the frame.
YSCAL(FRAME,VECTOR) is the Y-coordinate of the vector as seen from the frame.
ZSCAL(FRAME,VECTOR) is the Z-coordinate of the vector as seen from the frame.
TABLE is a frame which has standard table coordinates.
A LIST OF CONTINUOUSLY EVALUATED FUNCTIONS:
TORQUE: VECTOR → REAL
FORCE: VECTOR → REAL
DISTANCE(<FRAME>,<FRAME>) This is the distance between the
two frames. If one of the frames is an arm, then this means the closest
distance.
DEFERRED EVALUATION
This is a discussion of the syntax and semantics of
expressions. In every case, we describe the compile-time and the
run-time effects of the statement containing the expression.
The most straightforward kind is the following: To set a
value in a frame: FROB ← (3 2 0) ≡ (0 π 0) will just put that value
into FROB, and generate code which loads the constant into the
runtime cell reseved for FROB.
Slightly more complicated: NEWFROB ← FROB + (1 3 2) Causes
immediate compile-time calculation of NEWFROB for the benefit of the
compiler, and generates code which will take the current value of
FROB and do the appropriate arithmetic, storing the result in the
cell for NEWFROB.
Even more complicted: FIXEDFROB ← ∀ FROB + (1 3 2) The symbol
∀ is a unary operator by syntax, and means "always". It causes
evaluation of its argument to be postponed until needed. The
generated code is the same as for the previous case, but every time
the value of FROB is changed, code will be generated to appropriately
change FIXEDFROB. In this case, the updating will be a "position"
updating only. It is also possible to cause an "orientation update"
only. An example of this is FIXEDFROB ← ∀ FROB ∂ (0 π π/2). The
third simple case is a "complete update", caused by something like
FIXEDFROB ← ∀ FROB * (A→B). Any more compilicated expression will
cause each change in FROB to generate explicit code for the update of
FIXEDFROB.
If FIXEDFROB is, say, the endpoint of some trajectory, then
it will be evaluated at trajectory-planning time on the basis of the
current (compile-time) version of FROB. At run-time, the trajectory
will be modified to bring it in line with the current (run-time)
version of FROB.
The above discussion applies equally well to vectors and
planes.
When the statement ATTACH FROB TO BASE occurs, this has the
same effect as the statement FROB ← (BASE→FROB) * ∀ BASE. The
statement DETACH FROB has the effect of causing all deferred
evaluations to be carried out, and the resulting constant to be
assigned to FROB. No code is generated.
In order to set FROB to, say, (a b c)≡(w α β) with respect to
PUMPBASE, one can say FROB ← (A B C)≡(W α β) * (TABLE→PUMPBASE).
Since this is a bit wordy, the construct PUMPBASE can be used instead
of TABLE→PUMPBASE whenever a trans expression is unambiguously
required.
DATA STRUCTURES FOR REPRESENTATION OF OBJECTS.
New datatype: ATOM. Consists of property list. Each property has
a name, depending on what kind of atom it is.
OBJECT ATOM: all the knowledge needed about a (possibly hypothetical) object.
LOCATION (LOCATION ATOM)
MASS (SCONST)
MOMENT1 (VCONST)
MOMENT2 (VCONST)
STABILITIES (LIST OF STABILITY ATOMS)
GRASPS (LIST OF GRASP ATOMS)
SUBPARTS (LIST OF OBJECT ATOMS)
USER-DEFINED (anything whatsoever)
AFFIXION (OBJECT ATOM) to whom this object is affixed.
LOCATION ATOM: where something is.
LOCUS-FORM (FEXP) may be parameterised.
DETERMINATION (FEXP) represents what is known about locus.
NOMINAL VALUE (FCONST) usually centroid of locus-form.
STABILITY ATOM: how the object can safely rest.
LOCATION (FCONST) with respect to the locus-form.
FOOTPRINT (FCONST) of a coffee cup looks like a dunce+cap.
GRASPS (LIST OF GRASP ATOMS) only those allowed from this spot.
GRASP ATOM: where to grab object.
OPENING (SCONST)
DEPROACH (FCONST)
HANDSHAKE (SCONST) how hard may grasp without mauling.
STABILITIES (LIST OF STABILITY ATOMS) only those at which this grasp legal.
COMPILE TIME AND RUNTIME MODIFICATION OF VARIABLES
→→→→→→this page is currently undergoing change. It is wrong.
The question arises concerning what to do if the actual
location of a frame is not exactly the same as its planned location.
Say that the actual location has been determined by means of a
search. What one wants to do is to say, "whenever I say FROB, I no
longer mean my planned FROB, but rather the FROB that I have just
located." This can be done by the following code:
FROB ← <some calculations based on hand position>
The effect of this is to cause the runtime program to read the hand,
do the calculations, and modify the cell for FROB so that
future trajectories using FROB will be appropriately modified.
ASSUME FROB AT <some frame expression, possibly depending on hand>
The effect of this is to cause the compiler to modify its world.
No code is generated.
Now the big question: what does all this gain us? It allows
us to plan trajectories even when we knw that the actual locations we
are using are somewhat suspect. It renders the system tolerant to
location errors. Exactly how tolerant is a matter for investigation.
If the servo tries to run a trajectory which has been slightly
modified (say less than 10 centimeters), the chances are good that
nothing bad will happen. As the correction grows, though, the
following bad effects begin to appear:
1) The timing is off. Not enough time to move the arm the requisite
distance. The arm moves too fast.
2) The careful avoidance of collisions goes to waste; the margin of
clearance becomes negative.
3) The selection of which joints are to be free, and which are to
sense force becomes wrong (this selection is currently not made at
runtime); even before this, the quantitative measurement of force
becomes innacurate.
4) The arm tries to go past its stops.
CONTROL STRUCTURES.
The overall outline of the program is this:
A set of declarations followed by a set of statements.
Statements can cause the execution of other statements out of line,
by means of the EXECUTE subcommand.
It is envisioned that most statements will have labels and will be
treated as subroutines. There will also be procedures with
parameters, as well as macros. Block structure will be implemented.
The major problems seem to be these:
1) The status of variables will change at run time between
stable and instable. Trajectory calculations will be possible at
compile time only for stable or fuzzy variables; other calculations
must be deferred until the requisite variables are at least fuzzy.
Some of this run-time scheduling of computation should be managed by
the run-time routines, but some must perforce be under programmer
control.
2) In iterations, the variables used may change their
status. That is, the compiler may never know whether a variable is
to be taken as fixed, unless it is explicitly told.
Recursion may be a nice feature. For example, programming the arm
to solve the Tower of Hanoi problem requires recursion. This opens
an entire box of difficulties concerning saving old values of
variables for later restoration upon recursive ascent.
Some forms of iteration, at least, must be implemented. I suggest
the following constructs:
WHILE <boolean> DO <statements>
FOR <control id> ← <arith expr> [STEP <arith expr>] UNTIL
<arith expr>
DO <statements>
IF <BOOL> THEN <STATEMENT> [ELSE <STATEMENT>]
GOTO <label> {uggh!}
EXECUTE <label> {Like a F0RTRAN CALL}
DONE {Terminate loop. This can also be used to terminate a
MOVE}
CONTINUE {Terminate this iteration; continue the loop}
SAIL - type forks and joins for disassociating truly independent
motions should be included as an alternative to the DURING notation.
The syntax for these has not yet been worked out.
IDEAS WHICH MUST BE THOUGHT OUT. THEIR TIME HAS ALMOST COME.
Should there be a datatype OBJECT? What sort of fields would it
have? How would it be related to frames? STANDARD DESCRIPTIONS OF
OBJECTS SHOULD IN SOME WAY BE COMPATIBLE. IT SHOULD NOT BE NECESSARY
FOR STRATEGY PROGRAMS TO CONTORT THEIR USUAL WAY OF REPRESENTING
OBJECTS. →→→→→This might be getting into more model-based stuff
than we want. -- RF
PERHAPS STANDARD APPROACH SHOULD BE AN OPTIONAL PROPERTY OF FRAMES.
THIS THEN IS THE DEFAULT WHEN NO EXPLICIT APPROACH OR DEPARTURE ARE
MENTIONED. THE APPROACH FOR THE FRAME "TABLE" SHOULD THEN BE (0 0
3). →→→→→I think this is a good idea. Any takers?
HAL SHOULD BE IN SOME SENSE A MONITOR CAPABLE OF COMPILING, SAVING,
EDITING, TESTING, AND LINKING PROCEDURES, WITH DIAGNOSTICS TO
CONSOLE FOR EACH PHASE.
For the sake of consistency, it would be good to have arithmetic
operators which effect the rotation of frames. How could we specify
a rotation? Of course, the methods already described (ie Bolles,
Euler, and Finkel angles) can be used. Do we need more flexibility?
OTHER PROPERTIES OF FRAMES:
SUCH AS STANDARD APPROACH/DEPARTURES, OBJECT MASSES, AXES OF
INSERTION AND PERHAPS PROGRAMMER-DEFINED PROPERTIES.
THE FIXING OF ONE FRAME TO ANOTHER SHOULD DO THE RIGHT
THINGS FOR MASS, WHATEVER THEY MIGHT BE.
IT SHOULD BE POSSIBLE TO REPEATEDLY FIX AND UNFIX FRAMES TO OTHER
FRAMES. Say the yellow has moved to frame FROB. Say HOLE is a frame
fixed to FROB. Say we want to move the frob so HOLE coincides with
frame HOLESPOT. Use the following code:
ATTACH FROB TO YELLOW;
MOVE HOLE TO HOLESPOT;
COMMENT: Since HOLE is fixed to FROB, which is now attached
to YELLOW, this command is translated into a motion
for the yellow hand;
An alternative fomulation might be:
ATTACH FROB TO YELLOW;
MOVE YELLOW TO (SUCH THAT HOLE=HOLESPOT);
Note the interesting consequences of attaching one hand to the
other. Then a motion of one hand forces the other to move in a
coordinated way. I guess it even forces the orientations to come out
right.
THE FOLLOWING PAGES ARE FOR COMMENTS & COMPLAINTS BY POTENTIAL USERS.
... SAMPLE PROGRAM : SLIP_OVER (OCT 10)
A sample program (or piece thereof):
...... in the main program ......
INTEGER K, STATUS;
FRAME (DEF_WRT TABLE) CLUTCH_SLEEVE;
FRAME (DEF_WRT CLUTCH_SLEEVE) SLEEVE_HOLE;
PRELOAD_WITH (EULER 0,0,0,0,0, 1.6); COMMENT preloads frame above;
FRAME ROLLER_BEARING; COMMENT if no `WRT' is stated, the default is
the TABLE frame (or default could be set);
FRAME PS_SUBASSEMBLY;
FRAME (FIXDEF_WRT PS_SUBASSEMBLY) CLUTCH_END;
PRELOAD_WITH (BOLLES 180,0,0, 0,0,2.92);
FRAME (FIXDEF_WRT PS_SUBASSEMBLY) FLYWHEEL_END;
PRELOAD_WITH (EULER 0,0,0, 0,0,-2.86);
.
.
.
MACRO SLIP_OVER(FRAME SHFT_END; FRAME SLEEVE_HOLE;
REAL MAX_DIST;
REAL DISTANCE_TO_MAIN_SHAFT;
REAL STEP_DISTANCE; INTEGER NUMBER_OF_STEPS;
REAL STEP_STOPPING_FORCE;
REAL FINAL_STEP, FINAL_STOPPING_FORCE);
BEGIN COMMENT assume the yellow hand has already picked up the `sleeve'
to be slipped over the `shaft' ... and attached it to the hand.
the steps are:
(1) move the sleeve so that it is aligned with the shaft and is just
off the end of the shaft
(2) search to slip the sleeve over the end ... just a little way
(3) slip onto main shaft ... not stopping on force, but checking time
(4) loop to slide along the shaft in a number of steps
(5) a final push against the end (if FINAL_STEP>0.0);
COMMENT step 1 ... move close to end of shaft;
MOVE SLEEVE_HOLE TO SHAFT_END - .2*Z.SHAFT_END;
COMMENT Z.**** is a predefined construction which produces
a unit vector in the Z direction of the indicated frame;
USING APPROACH (-3*Z.SHAFT_END);
COMMENT step 2 ... search to slip over a little;
SEARCH YELLOW
AROUND SHAFT_END COMMENT meaning to search in the X-Y plane of frame;
INCREMENT .2
ON (FORCE(Z.SHAFT_END) > MINIMUM(Z.SHAFT_END)+20) DO GOTO STEP_3;
ON (DISTANCE_FROM_START > MAX_DIST) DO
BEGIN OUTPUT("FAILED TO SLIP OVER AT ALL");
STATUS ← 2; COMMENT global flag-like variable;
STOP;
END;
COMMENT thus the search continues until one of the ON criteria is
satisfied ... could have a variety possible eg.
ON (NUMBER_OF_SEARCH_STEPS > 16) DO .... ;
COMMENT step 3 ... slip onto main shaft ... hopefully;
STEP3: MOVE TO ⊗+DISTANCE_TO_MAIN_SHAFT*Z.SHAFT_END
USING FREE(X.SHAFT_END, Y.SHAFT_END)
ON (TIME > 60) DO BEGIN OUTPUT("OUT OF TIME GOING TO MAIN");
STATUS ← 3;
RETURN;
END;
COMMENT step 4 ... slipping along the shaft ... in N steps;
FOR K ← 1 STEP 1 UNTIL NUMBER_OF_STEPS DO
MOVE TO ⊗+[0, 0, STEP_DISTANCE] WRT SHAFT_END; COMMENT just another
way of stating "STEP_DISTANCE*Z.SHAFT_END";
USING FREE(X.SHAFT_END, Y.SHAFT_END);
ON FORCE(Z.SHAFT_END) > 100 DO BEGIN OUTPUT("STUCK ALONG SHAFT");
STATUS ← 4;
RETURN;
END;
COMMENT step 5 ... giving it the final push;
IF FINAL_STEP > 0.0 THEN
MOVE TO ⊗ + FINAL_STEP*Z.SHAFT_END
USING FREE(X.SHAFT_END, Y.SHAFT_END)
ON FORCE(Z.SHAFT_END) > FINAL_STOPPING_FORCE DO RETURN;
OUTPUT("DIDN'T REACH FORCE ON THE FINAL PUSH");
STATUS ← 5;
RETURN;
END "SLIP_OVER";
.
.
.
PICKUP(CLUTCH_SLEEVE ...
SLIP_OVER(CLUTCH_END, ...
... SAMPLE PROGRAM : PUT_PISTON_IN_VISE (OCT 12)
→→→→→REVISED AS TO SYNTAX 11/3/73
... global definitions ...
FRAME PS_SUBASS; COMMENT THIS IS DEFINED WRT TABLE BY DEFAULT;
FRAME (FIXDEF_WRT PS_SUBASS) CLUTCH_END;
PRELOAD_WITH BOLLES(-2.86, 0, 0, 0, -90, 0);
FRAME (FIXDEF_WRT PS_SUBASS) FLYWHEEL_END;
PRELOAD_WITH BOLLES(2.96, 0, 0, 0, 90, 0);
FRAME (FIXDEF_WRT PS_SUBASS) CAP;
PRELOAD_WITH BOLLES(0, 0, .6, 0. 180., 0);
VECTOR (FIXDEF_WRT PS_SUBASS) SHAFTV;
PRE_LOAD_WITH [1, 0, 0];
FRAME VISE; COMMENT assumed to be wrt(table);
VECTOR SHFT, PREDICTED_C_END;
FRAME T_CAP, F_END, C_END, PRE_C_END;
REAL A;
INTEGER I;
PROCEDURE PUT_PISTON_IN_VISE;
BEGIN COMMENT assume the hand has already picked up the piston at position
`cap' on the PS_SUBASS ... this procedure puts subassembly into the
vise, feels the flywheel end, uses its position to prodict the position
of the clutch_end, then feel the clutch_end, use the two end locations
to determine the location of the shaft, update the location of the
subassembly (reset its frame value) ...;
MOVE YELLOW
TO VISE + [0, 0, 1.0]; COMMENT correction for hand above vise;
USING APPROACH([0, -3, 0] WRT VISE, MAX_VELOCITY=SLOW?
CLOSE_VISE
ON (VISE_OPENING < 1) DO
BEGIN OUTPUT("PS_SUBASS NOT GRIPPED BY VISE???");
RETURN;
END;
OPEN 3;
CENTER
ON (GRASP < .4) DO STOP;
T_CAP ← @; COMMENT save the current location for future computing;
FEEL_POINT(3, [3,-3,3], 3, FSA, SHFT3, FSA, 90);
COMMENT this routine feels the flywheel end twice ... and saves
resulting location in F_END for further computation;
SHFT ← (XYZ[T_CAP] - [0, 0, .6]) - XYZ(F_END);
COMMENT seems nicer to directly say XYZ(<FRAME>) rather than
table↓t_cap ... this statement computes a vector along shaft;
SHFT ← SHFT/LENGTH(SHFT); COMMENT makes SHFT a unit vector
maybe we should have UNIT(...), LENGTH(...), as built-in fns;
PREDICTED_C_END ← XYZ(T_CAP) + 2.86*SHFT;
PRE_C_END ← T_CAP - [0, 0, .6] + PREDICTED_C_END; COMMENT this is the
place where the hand is going to feel for the clutch end ...
all of this computation could be done in one statement:
PRE_C_END ← (T_CAP - [0,0,.6]) + 2.86*UNIT(XYZ(T_CAP-[0,0,.6])-
XYZ(F_END));
A ← -.1;
I ← 0; COMMENT increment for loop;
WHILE (I ≤ 4) DO
BEGIN
OPEN 3;
MOVE TO PRE_C_END + [0, 0, I*A];
CENTER ON SUCCESS DO DONE "LOOP";
I ← I + 1;
A ← (-1)*A;
END;
IF I = 5 THEN BEGIN OUTPUT("CAN'T FIND THE CLUTCH END");
RETURN;
END;
COMMENT this seems clumsy ... want a loop with two possible exits
(1) tried all possibilities and none worked
(2) found one that worked
and of course want to do two different things ... GOTO's might
make it more readable ... ???
→→→→→I CHANGED IT A TRIFLE. BETTER? --RF 11/3/73
C_END ← @; COMMENT now have both ends ... C_END & F_END;
COMMENT compute a unit vector along the shaft: SHAFTV
DON'T have to compute SHAFTV ... define it fixed wrt PS_SUBASS
update the position of the PS_SUBASS ... probably by calling
another procedure or possibly sending messages to a hairy prog
which updates frames, given points on planes, points=points, etc.;
UPDATE(PS_SUBASS, T_CAP, C_END, F_END);
END OF PUT_PISTON_IN_VISE;
... A REWORK OF PUT_PISTON_IN_VISE (W/ SETS, RESTORES ...NOV 6)
...first a macro for feeling a point ... ie. move to the point,
center, save discrepency, rotate some number of degrees,
center again, save discrepency ... hopefully by then you
have a good estimate of where the point is (ie. you have
produced a restoring trnasform which moves the planned position
for the point to a `better' estimate of the position for the point)
...used to improve the location of end of the shaft ... used to
improve the location of a bolt, pin, valve opening, etc.
...consider the following "attach" structure of frames ...
TABLE
YELLOW
FROB
FROB_HOLE
FROB_GRASP
BLUE
BEAM
BEAM_HOLE
...thinking about the following instructions and ideas:
every frame can have an `automatic restore' associated with it ...
this means that each time that frame is referenced, the compiler
should check to see if it has (ie. needs) such a restore, if so
the compiler should generate code to use it ... it also seems
reasonable to set this up so that if frames are attached to
each other, and if one frame has an auto restore, then anything
`under' it in the attachment structure should also be automatically
restored ... eg. if FROB has an auto restore, then the use of
FROB_HOLE should be autoamtically updated too. What about frames
above it in the attach structure ... probably not automatically
updated ... finding a better estimate for FROB may not tell you
anything about the position of the yellow hand even though
the FROB is being held in the hand ... the grasping position may
not be known very well ...
SET FROB_HOLE → BEAM_HOLE ... would set up a transform which
modifies the planned position of FROB_HOLE to the actual
position of BEAM_HOLE (which could have auto restore too)
... if you want the setting of FROB_HOLE to set the position
for the whole FROB, use a statement like:
SET FROB BY FROB_HOLE → BEAM_HOLE
question ... what if FROB_HOLE has an automatic restore and
FROB is set? shouldn't the FROB_HOLE lose its auto restore?
MAY not want this if at run time it has been determined that
this FROB has its hole in a slightly different relative position
than usual ... this would require the compiler to tack on
a string of auto restores ... one for FROB and one for FROB_HOLE ...
how does this relate to run-time calculations based upon FROB
FROB_HOLE, etc.??? at run-time certainly want best postional info
presumably any position computed and used at run-time must be
approximated at compile-time so the compiler has some clue
where things are going to happen ... this seems to imply that
any modifications at run time have to be done by SETS and RESTORES
UNLESS ... servo can calculate things for you ... maybe GOs and GOTOs.
not sure what auto restores do if frame is sent to a procedure
may need an ASSUME FRAME AT (...) to give compiler something to
use as a mental picture for compiling ...
for regular restores may want SAVE F1→F2 IN T, RESTORE T
all of this is assuming that the compiler has to have a mental
picture for everything ... and that the various instructions
affect this mental picture in some planned way ... eg. CENTER,
OPEN, SEARCH, etc. don't change mental position ... but MOVE,
GO, etc. do ... what about FREE and STOPPING ON FORCE?
MACRO FEEL_POINT(REAL OP1, VECTOR DEP, REAL OP2, VECTOR APP, FRAME POINT,
VECTOR AXIS, REAL DEG);
BEGIN COMMENT OP1 ... opening used to leave current position
DEP ... depart vector from current position
OP2 ... opening used to approach the POINT
APP ... approach vector to the POINT
POINT ... the transform (frame) for the point
AXIS ... axis about which the hand rotates DEG degrees for touch;
OPEN OP1
MOVE YELLOW TO POINT
USING DEPARTURE=DEP, APPROACH=APP;
DURING OPEN OP2; COMMENT if POINT has an automatic
restore associated with it, the compiler should
add it in to the MOVE;
CENTER
IF GRASP < .1 THEN ....
SET POINT → ⊗; COMMENT compiler should note that POINT now has a
new assumed position (ie. a new restore transform) and
should use it whenever POINT is referenced ... question:
what should stop or override this automatic restoring???
(1) another SET on that frame of a frame it is attached
under (or over if specifically stated) ... (2) moving the
frame or any frame it is attached to ... (3) ??? ...
An explicit restore on POINT should be in addition to
the automatic restore? seems correct ... this would be
something like a standard relative position from POINT,
so the resulting object code would be:
MOVE TO POINT
RESTORE BETTER_ESTIMATE_OF_POINT
RESTORE RELATIVE_POSITION_FROM_POINT;
COMMENT notice that the SET will do the right thing if
the POINT already has an automatically used restore ...
ie. the planned position for POINT as far as the compiler
is concerned is the uncorrected position of POINT ... thus
the set will actually create a transform which is cummulative
in the sense that it moves POINT (without the auto correction)
to the current run-time position ... which was arrived at
by using the auto correction, but the compiler has no way
of knowing or guessing what that correction is...;
OPEN OP2
MOVE TO POINT modified by DEG about AXIS
USING DEPARTURE=APPROACH=NIL; COMMENT since POINT has
been SET, it has an automatic RESTORE associated with
it that the compiler should insert;
CENTER
IF GRASP < .1 THEN ....
SET POINT → ⊗; COMMENT notice that this `auto restore' is a single
transform which corrects the planned position of the POINT;
END "FEEL_POINT";
... RANDOM COMMENTS
Instead of thinking of `a program' in HAL ... I would rather think
of a `conversation' with HAL (2001 here we come) ... that is, HAL should
be able to handle commands like: EDIT <PROCEDURE> DEFINE VECTOR X
COMPILE <PROCEDURE> EXECUTE <PROCEDURE> DISPLAY X
DO: X ← [1, 0, 1.5] SAVE <PROCEDURE> READ <PROGRAM>
... This view implies HAL is a monitor which can call on its own
editor, compiler, debugging routines, etc.
→→→→→→10/15/73 THIS LOOKS RIGHT. I WILL SOON PUT IN A PAGE ON THE OVERALL
STRUCTURE OF A HAL RUN.
→→→→→→11/3/73 I HAVE REMOVED MOST OF THIS PAGE, BECAUSE IT WAS OBSOLETE.
... SAMPLE PROGRAM : BOLT_ON_FROB (OCT 22)
→→→→→REVISED AS TO SYNTAX 11/3/73
...global definitions ...
...the world of objects (frames,etc.) initially looks like:
TABLE
BLUE
YELLOW
BEAM
BEAM_HOLE
FROB
λ∞rOB_HOLE
FROB_GRASP
BOLT
...this is defined as follows:
FRAME BEAM;
FRAME (FIXDEF_WRT BEAM) BEAM_HOLE;
PRELOAD_WITH (BOLLES 2 6 5 0 90 0);
FRAME FROB;
FRAME (FIXDEF_WRT FROB) FROB_HOLE;
PRELOAD_WITH (BOLLES 0 4 1 0 90 0);
FRAME (FIXDEF_WRT FROB) FROB_GRASP;
PRELOAD_WITH (BOLLES 2 0 1 0 180 0);
FRAME BOLT;
...the object of this program is to bolt the FROB to the BEAM by screwing
a bolt thru the FROB_HOLE into the BEAM_HOLE ... of course aligning FROB
correctly
MACRO PICKUP(ARM, OBJECT, GRASP_POS, APPR, OPENING, THICKNESS);
BEGIN COMMENT this is a macro which picks up an object (with the
specified ARM's hand) and ATTACH's the object to the hand.
This is done as follows:
(1) open the hand to maximum (to leave current place)
(2) move to the grasping position ... using specified
APPRoach ... and simultaneously closing to the
OPENING specified for grasping the object
(3) centers the hand & checks to make sure that the
opening doesn't become less than THICKNESS (which
indicates that the hand missed the object ... in which
case the arm prints a message to the operator and
waits for the operator to place the object in the correct
spot ... when the operator has done this he types a
"P" and the arm can try again);
OPEN ARM 4; COMMENT notice specification of "which" hand to open;
MOVE ARM TO GRASP_POS
USING APPROACH = APPR
DURING OPEN OPENING;
RETRY: CENTER ON GRASP < THICKNESS DO
BEGIN OUTPUT(STRING(ARM) &" DID NOT GRASP THE OBJECT "&
STRING(OBJECT) CRLF
"PLACE OBJECT IN ITS PROPER POSITION AND TYPE A `P'
TO RETRY" CRLF);
OPEN ARM 4
WAIT COMMENT arm waits for operator's response;
GOTO RETRY;
END;
ATTACH OBJECT TO ARM COMMENT notice that implies that at compile-time
the compiler has to know where the hand and
object are WRT each other ... this is
generally OK, except if wobbles or stop on
force or some freedom has been given to
the hand ... thus we should have an
assumption for where something is at the
moment;
END OF PICKUP;
MACRO BOLT_ON_FROB
BEGIN COMMENT this macro bolts on the FROB to the BEAM and ATTACH's
the FROB to the BEAM ... for completeness the bolt is also
ATTACHed to the BEAM ...
this is done using two hands (FORK'S AND JOIN'S) as follows:
(1) pickup the FROB in the yellow hand ... move it to
the BEAM and align the two holes
(2) at the same time pickup the bolt in the blue hand
(3) when both of those have been done ... move the bolt
to the insertion spot, insert it by searching, and
screw it in (freeing the yellow hand so FROB can
move up next to the BEAM as the bolt is tightened)
(4) attach the FROB to the BEAM;
FORK L1;
PICKUP(YELLOW, FROB, FROB_GRASP, ([0 0 -3] WRT FROB_GRASP), 1, .2);
COMMENT notice that after picking up the FROB the world is:
TABLE
YELLOW
FROB
FROB_HOLE
FROB_GRASP
BLUE
BEAM
BEAM_HOLE
BOLT;
MOVE FROB_HOLE TO BEAM_HOLE + [.1 0 0] WRT BEAM_HOLE;
JOIN L2;
L1: PICKUP(BLUE, BOLT, BOLT, ([0 0 -3] WRT BOLT), .8, .4);
COMMENT again probably assume default approach of 3" in
the minus Z direction of the grasping position ...;
JOIN L2;
L2: MOVE BOLT TO BEAM_HOLE - [0 0 1.7] WRT BEAM_HOLE;
SEARCH BLUE
INCREMENT .1
REPEATING BEGIN MOVE TO ⊗ + [0 0 .5] WRT BLUE
ON FORCE(Z.BLUE) > 50 DO CONTINUE
DONE
END;
COMMENT shaky ... assume plane of search is perpendicular
to current position of the hand ... should say
something about moving back to "original position
plus the increment" or something ... CONTINUE means
stop this trip thru the loop and begin the next ...
DONE means stop the loop all together;
MOVE BLUE TO ⊗ + [0 0 1.5] WRT BLUE
ON FORCE(Z.BLUE) > 50 DO STOP;
USING FREE(Z.FROB_HOLE);
COMMENT means compiler has to figure out where FROB_HOLE is
etc. notice that it is in yellow hand ....;
MOVE BLUE TO ⊗
THEN BEGIN OUTPUT("DIDN'T REACH TORQUE")
...
END;
USING FREE(X.BLUE, Y.BLUE, Z.BLUE, Z.FROB_HOLE),
DURING SCREW(60)
ON TORQUE(Z.BLUE) > 100 DO STOP
OPEN BLUE 4;
END OF BOLT_ON_FROB;
... MORE COMMENTS (WHILE I'M THINKING OF THEM)
We should probably start a "reserved word list"
Where did the name "HAL.SAM" come from???
→→→→→→HAL.SAMPLE, of course. See page 2.
...
...